using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using PHSRAG.Utility;

namespace PHSRAG.WebControls
{
	#region class DownloadBar
	/// <summary>
	/// Custom control providing download to Excel and PDF, and e-mailing functionality.
	/// The DownloadBar relies on the page to tell it what needs to be packaged, so event handlers must be created
	/// by the page if report formatting functionality is required.
	/// </summary>
	[ToolboxData("<{0}:DownloadBar runat=server />")]
	[Designer(typeof(DownloadBarDesigner), typeof(IDesigner))]
	public class DownloadBar : WebControl,  INamingContainer
	{
		#region Constants

        private const string ConfigKeyReportHostPage = "Rpt.ReportHostPage";

		private const string InternalExcelCommand		= "Export Internal View to Excel";
		private const string ExcelCommand				= "Download to Excel";
		private const string PDFCommand					= "Download to PDF";
		private const string EmailCommand				= "Send by E-mail";		
		private const string FailedActionCommand		= "FailedAction";
		
		private const string StyleNameKey				= "StyleName_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private const string EnableInternalExcelLinkKey	= "EnableInternalExcelLinkKey_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private const string EnableExcelLinkKey			= "EnableExcelLink_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private const string EnablePDFLinkKey			= "EnablePDFLink_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private const string EnableEmailLinkKey			= "EnableEmailLink_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private const string ReportHostPageKey			= "ReportHostPage_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
        private const string SQLReportNameKey           = "sqlRptName";
        private const string InternalSQLReportNameKey   = "InternalsqlRptName";
        
		private const string ExportFormatTypeKey		= "ExportFormatType_942A8F60-DF24-467f-AC0D-95FE620B0CEE";

		#endregion

		#region Static Variables (private)
		// This control can't access the Keys class in the WebSite project, so I have to create local keys here.
		private static string reportStreamKey			= "ReportStream_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private static string reportHostScriptKey		= "ReportHostScript_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
        private static string SQLReportHostScriptKey       = "SQL_ReportHostScript_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private static string reportFilePathKey			= "ReportFilePath_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		private static string reportContentTypeKey		= "ReportContentTypeKey_942A8F60-DF24-467f-AC0D-95FE620B0CEE";
		#endregion

		#region Instance Variables
		/// <summary> Button to download special data into Excel. </summary>
		private LinkButton downloadInternalToExcel;
		/// <summary> Button to download current page info to Excel. </summary>
		private LinkButton downloadToExcel;
		/// <summary> Button to download current page info to PDF. </summary>
		private LinkButton downloadToPDF;
		/// <summary> Button to send summary e-mail. </summary>
		/// <remarks>
		/// Not implemented in this control; application specific.
		/// This instance variable is protected to facilitate this functionality.
		/// </remarks>
		protected LinkButton sendByEmail;
		
		/// <summary> Image to download current page into PDF </summary>
		private ImageButton PDFLink;
		/// <summary> Image to download current page into Excel </summary>
		private ImageButton excelInternalLink;
		/// <summary> Image to download current page into Excel </summary>
		private ImageButton excelLink;
		/// <summary> Image to download current page into e-mail </summary>
		protected ImageButton emailLink;
		/// <summary>Name of the report.</summary>
		protected string reportName;
		/// <summary>Column count.</summary>
		protected int columnCount;
		/// <summary>Record count.</summary>
		protected int recordCount;
		#endregion

		#region Properties
		/// <summary>
		/// Get/Set the CssClass
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Get/Set the CssClass")]
		public string StyleName
		{
			get
			{ 
				object o = ViewState[StyleNameKey];
				return (o == null) ? "DownloadBar" : (string)o;
			}
			set
			{
				ViewState[StyleNameKey] = value;
			}
		}

        /// <summary>
        /// Get/Set the enabled property to control if the Excel link is enabled or not.
        /// </summary>
        [Bindable(true), Category("Behavior"), Description("Get/Set the enabled property to control the script file to use")]
        public bool useRootHost
        {
            get
            {
                object o = ViewState["rootHost"];
                return (o != null) ? true : false;
            }
            set
            {
                ViewState["rootHost"] = value;
            }
        }

		/// <summary>
		/// Get/Set the enabled property to control if the Internal Excel link is enabled or not.
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Get/Set the enabled property to control if the Internal Excel link is enabled or not")]
		public bool EnableInternalExcelLink
		{
			get
			{ 
				object o = ViewState[EnableInternalExcelLinkKey];
				return (o == null) ? false : (bool)o;
			}
			set
			{
				ViewState[EnableInternalExcelLinkKey] = value;
			}
		}

		/// <summary>
		/// Get/Set the enabled property to control if the Excel link is enabled or not.
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Get/Set the enabled property to control if the Excel link is enabled or not")]
		public bool EnableExcelLink
		{
			get
			{ 
				object o = ViewState[EnableExcelLinkKey];
				return (o == null) ? true : (bool)o;
			}
			set
			{
				ViewState[EnableExcelLinkKey] = value;
			}
		}

		/// <summary>
		/// Get/Set the enabled property to control if the PDF link is enabled or not.
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Get/Set the enabled property to control if the PDF link is enabled or not")]
		public bool EnablePDFLink
		{
			get
			{ 
				object o = ViewState[EnablePDFLinkKey];
				return (o == null) ? true : (bool)o;
			}
			set
			{
				ViewState[EnablePDFLinkKey] = value;
			}
		}

		/// <summary>
		/// Get/Set the enabled property to control if the Email link is enabled or not.
		/// </summary>
		[Bindable(true), Category("Behavior"), Description("Get/Set the enabled property to control if the Email link is enabled or not")]
		public bool EnableEmailLink
		{
			get
			{ 
				object o = ViewState[EnableEmailLinkKey];
				return (o == null) ? false : (bool)o;
			}
			set
			{
				ViewState[EnableEmailLinkKey] = value;
			}
		}

		/// <summary>
		/// Get/Set the ReportHostPage property to specify a page for Excel spreadsheets/PDFs to open in
		/// </summary>
		/// <remarks>
		/// Required for all pages consuming this control.
		/// </remarks>
		[Bindable(true), Category("Behavior"), Description("Get/Set the popup host page for displaying reports.")]
		public string ReportHostPage
		{
			get
			{ 
				object o = ViewState[ReportHostPageKey];
				return (o == null) ? string.Empty : (string)o;
			}
			set
			{
				ViewState[ReportHostPageKey] = value;
			}
		}

        /// <summary>
        /// Get/Set the ReportName property to specify the name of the report to render from the SSRS server
        /// </summary>
        /// <remarks>
        /// Required for all pages consuming this control.
        /// </remarks>
        [Bindable(true), Category("Behavior"), Description("Get/Set the ReportName property to specify the name of the report to render from the SSRS server")]
        public string SQLReportName
        {
            get
            {
                object o = ViewState[SQLReportNameKey];
                return (o == null) ? string.Empty : (string)o;
            }
            set
            {
                ViewState[SQLReportNameKey] = value;
            }
        }

 		[Bindable(true), Category("Behavior"), Description("Get/Set the ReportName property to specify the name of the report to render from the SSRS server")]
        public string InternalSQLReportName
        {
            get
            {
                object o = ViewState[InternalSQLReportNameKey];
                return (o == null) ? string.Empty : (string)o;
            }
            set
            {
                ViewState[InternalSQLReportNameKey] = value;
            }
        }
        
		/// <summary>
		/// Get the session key for the constructed Report stream
		/// </summary>
		/// <remarks>
		/// This control can't access the Keys class in the WebSite project, so I have to create local keys here.
		/// </remarks>
		public static string ReportStreamKey
		{
			get { return reportStreamKey; }
		}

		/// <summary>
		/// Get the script key for the ReportHostScript
		/// </summary>
		/// <remarks>
		/// This control can't access the Keys class in the WebSite project, so I have to create local keys here.
		/// </remarks>
		public static string ReportHostScriptKey
		{
			get { return reportHostScriptKey; }
		}

		/// <summary>
		/// Get the file path key to the file system where documents are staged.
		/// </summary>
		/// <remarks>
		/// This control can't access the Keys class in the WebSite project, so I have to create local keys here.
		/// </remarks>
		public static string ReportFilePathKey
		{
			get { return reportFilePathKey; }
		}

		/// <summary>
		/// Get the report content type the opening page should use to display the report.
		/// </summary>
		/// <remarks>
		/// This control can't access the Keys class in the WebSite project, so I have to create local keys here.
		/// </remarks>
		public static string ReportContentTypeKey
		{
			get { return reportContentTypeKey; }
		}

		/// <summary>
		/// Sets the number of columns the report will have.
		/// </summary>
		public int ColumnCount 
		{
			set { columnCount = value; }
		}

		/// <summary>
		/// Sets the number of records the report will have.
		/// </summary>
		public int RecordCount 
		{
			set { recordCount = value; }
		}

		/// <summary>
		/// Sets Formatter report name to be used by the ExcelFormatter to format excel report appropriately.
		/// </summary>
		public string ExcelFormatterReport
		{
			set 
			{
				reportName = value;
			}
		}
		#endregion

		#region Event
		/// <summary>
		/// Delegate used by page to send report as email link.
		/// </summary>
		public delegate void EmailEventHandler(out string webConfigURLKey, out int queryId, out Hashtable summaryInfo);

		/// <summary>Get/Set handler for the event raised when the requested action fails</summary>
		public event CommandEventHandler FailedAction
		{
			add		{ Events.AddHandler(FailedActionCommand, value); }
			remove	{ Events.RemoveHandler(FailedActionCommand, value); }
		}

		/// <summary>
		/// Add/Remove handler for the sendByEmail click.
		/// </summary>
		[Category("Action"), Description("Raised when Send by Email is clicked")]
		public event EmailEventHandler SendByEmail
		{
			add		{ Events.AddHandler(EmailCommand, value); }
			remove	{ Events.RemoveHandler(EmailCommand, value); }
		}
		#endregion

		#region Overrides
		/// <summary>
		/// Create all controls that will be on the DownloadBar. Notice that the creation is more than just instantiating
		/// the controls. It also involves in generating the underlying HTML so that the controls shows up per the need.
		/// </summary>
		protected override void CreateChildControls()
		{
		    string scriptSrc = useRootHost ? "../Scripts/SQLReport2.js" : "../Scripts/SQLReport.js";
            Page.ClientScript.RegisterStartupScript(GetType(), SQLReportHostScriptKey,
                   string.Format ("<script language='Javascript' type='text/javascript' src='{0}'></script>",scriptSrc));               
            CreateControls();
            GenerateControlTree();
		}

		/// <summary>
		/// Invoked when an event is raised by a child control.
		/// </summary>
		/// <param name="source">Reference to the child control that raised the event</param>
		/// <param name="e">Argument associated with the event</param>
		/// <returns>True if the event was handled by this method; false otherwise</returns>
		protected override bool OnBubbleEvent(object source, EventArgs e)
		{
			// Events raised only by link buttons are handled or if it is an image button
			//If an event handler is associated with the button, invoke it.
			bool handled = false;

			try
			{
                CommandEventArgs args = e as CommandEventArgs;
				if (args != null && (source is LinkButton) || (source is ImageButton))
				{
					switch (args.CommandName)
					{
						case ExcelCommand:
                            throw new ApplicationException("ExcelCommand not implemented.");
							

						case InternalExcelCommand:
                            throw new ApplicationException("InternalExcelCommand not implemented.");
							

						case PDFCommand:
                            throw new ApplicationException("PDFCommand not implemented.");
							

						case EmailCommand:
							// Get all required e-mail information and send an e-mail as requested.
							// NB: The SendEmail function in this control is a stub and must be filled in
							// on an application by application basis for e-mail to work.
							EmailEventHandler emailEvent = Events[EmailCommand] as EmailEventHandler;
							if (emailEvent != null)
							{
								string webConfigURLKey = "";
								int queryId = -1;
								Hashtable summaryInfo = null;
								emailEvent(out webConfigURLKey, out queryId, out summaryInfo);

								SendEmail(webConfigURLKey, queryId, summaryInfo);

								handled = true;
							}
							break;
					}
				}
			}
			catch (Exception ex)
			{
				CommandEventHandler handler = Events[FailedActionCommand] as CommandEventHandler;
				
                if (handler == null) throw;

			    handler(this, new CommandEventArgs("OnBubbleEvent", ex));
			}

			return handled;
		}

		/// <summary>
		/// Placeholder for application specific e-mail functionality. Override within application to fill in with business logic.
		/// </summary>
		protected virtual void SendEmail(string webConfigURLKey, int queryId, Hashtable summaryInfo) {}
		#endregion

		#region Protected Methods
		/// <summary>
		/// Create all controls in the DownloadBar.
		/// </summary>
		/// <remarks>
		/// Protected to facilitate application-specific send by e-mail functionality.
		/// </remarks>
		protected virtual void CreateControls()
		{
			Controls.Clear();

            string pageName = HttpContext.Current.Server.UrlEncode(Page.Request.Url.ToString());
            string reportHostPage = string.IsNullOrEmpty(ReportHostPage) ? ResolveUrl(Settings.GetKeyValue(ConfigKeyReportHostPage, string.Empty)) : ResolveUrl(ReportHostPage);
           
			if (EnableExcelLink)
			{
				// User links
				downloadToExcel = new LinkButton();
                downloadToExcel.Attributes.Add("onclick", "javascript:return GetReport('" + SQLReportName + "', 'Excel', '" + pageName + "', '" + reportHostPage + "');");
        
				downloadToExcel.CommandName = downloadToExcel.Text = ExcelCommand;

				excelLink = new ImageButton();
				excelLink.CommandName = ExcelCommand;
				excelLink.Enabled = downloadToExcel.Enabled;
				excelLink.ImageUrl = string.Format("{0}/Images/icon_xls.gif", IsDesignMode ? ".." : "~");
                excelLink.Attributes.Add("onclick", "javascript:return GetReport('" + SQLReportName + "','Excel','" + pageName + "', '" + reportHostPage + "');");
			}

			if (EnableInternalExcelLink)
			{
				// User links
				downloadInternalToExcel = new LinkButton();
                downloadInternalToExcel.Attributes.Add("onclick", "javascript:return GetReport('" + InternalSQLReportName + "','Excel','" + pageName + "', '" + reportHostPage + "');");

                downloadInternalToExcel.Text = InternalExcelCommand;

				excelInternalLink = new ImageButton();
				excelInternalLink.Enabled = downloadInternalToExcel.Enabled;
				excelInternalLink.ImageUrl = string.Format("{0}/Images/icon_xls.gif", IsDesignMode ? ".." : "~");
                excelInternalLink.Attributes.Add("onclick", "javascript:return GetReport('" + InternalSQLReportName + "','Excel','" + pageName + "', '" + reportHostPage + "');");
			}

			if (EnablePDFLink)
			{
				downloadToPDF = new LinkButton();
                downloadToPDF.Attributes.Add("onclick", "javascript:return GetReport('" + SQLReportName + "','PDF','" + pageName + "', '" + reportHostPage + "');");
                             
				downloadToPDF.CommandName = downloadToPDF.Text = PDFCommand;

				PDFLink = new ImageButton();
				PDFLink.CommandName = PDFCommand;
				PDFLink.Enabled = downloadToPDF.Enabled;
				PDFLink.ImageUrl = string.Format("{0}/Images/icon_PDF.gif", IsDesignMode ? ".." : "~");

                PDFLink.Attributes.Add("onclick", "javascript:return GetReport('" + SQLReportName + "','PDF','" + pageName + "', '" + reportHostPage + "');");
			}

			if (EnableEmailLink)
			{
				sendByEmail = new LinkButton();
				sendByEmail.CommandName = sendByEmail.Text = EmailCommand;
				sendByEmail.Enabled = IsDesignMode || (((Events[EmailCommand] != null) /*&& (EnableLinks == true)*/));

				emailLink = new ImageButton();
				emailLink.CommandName = EmailCommand;
				emailLink.Enabled = sendByEmail.Enabled;
				emailLink.ImageUrl = string.Format("{0}/Images/icon_email.gif", IsDesignMode ? ".." : "~");
				emailLink.Visible = false;
			}
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Setup the control tree to reflect the actual (and exact) layout of the controls within the DownloadBar.
		/// </summary>
		private void GenerateControlTree()
		{
			Table table = new Table();
			Controls.Add(table);
			table.CssClass = StyleName;

			TableRow row = new TableRow();
			table.Rows.Add(row);
			
			if (EnableExcelLink)
			{
				TableCell cell = new TableCell();
				row.Cells.Add(cell);
				cell.CssClass = "DownloadBarImage";
				cell.Controls.Add(excelLink);

				cell = new TableCell();
				row.Cells.Add(cell);
				cell.Controls.Add(downloadToExcel);
			}

			if (EnableInternalExcelLink)
			{
				TableCell cell = new TableCell();
				row.Cells.Add(cell);
				cell.CssClass = "DownloadBarImage";
				cell.Controls.Add(excelInternalLink);

				cell = new TableCell();
				row.Cells.Add(cell);
				cell.Controls.Add(downloadInternalToExcel);
			}

			if (EnablePDFLink)
			{
				TableCell cell = new TableCell();
				row.Cells.Add(cell);
				cell.CssClass = "DownloadBarImage";
				cell.Controls.Add(PDFLink);

				cell = new TableCell();
				row.Cells.Add(cell);
				cell.Controls.Add(downloadToPDF);
			}

			if (EnableEmailLink)
			{
				TableCell cell = new TableCell();
				row.Cells.Add(cell);
				cell.CssClass = "DownloadBarImage";
				cell.Controls.Add(emailLink);

				cell = new TableCell();
				row.Cells.Add(cell);
				cell.Controls.Add(sendByEmail);
			}
		}
		#endregion

		#region Internal Methods
		/// <summary>
		/// This method is ONLY invoked by the associated designer 
		/// to show the control contents at design time.
		/// </summary>
		internal void Design()
		{
			EnsureChildControls();
		}
		#endregion

		#region Private Properties
		/// <summary>
		/// Return true if the control is in design mode.
		/// </summary>
		private static bool IsDesignMode
		{
			get { return HttpContext.Current == null; }
		}
		#endregion
		
	}
	#endregion

	#region Class DownloadBarDesigner
	/// <summary>
	/// Designer associated with the control.
	/// </summary>
	public class DownloadBarDesigner : ControlDesigner
	{
		#region Overrides
		/// <summary>
		/// Force the control to create its child controls for display at design time.
		/// </summary>
		/// <returns>HTML representation of the control</returns>
		public override string GetDesignTimeHtml()
		{
			((DownloadBar)Component).Design();
			return base.GetDesignTimeHtml();
		}
		#endregion
	}
	#endregion
}
// --- EOF ---